<template>
  <el-form ref="form" :model="spuForm" label-width="100px">
    <el-form-item label="SPU名称">
      <el-input v-model="spuForm.spuName" placeholder="SPU名称"></el-input>
    </el-form-item>
    <el-form-item label="品牌">
      <el-select v-model="spuForm.tmId" placeholder="请选择品牌">
        <el-option :label="tm.tmName" :value="tm.id" v-for="tm in trademarkList" :key="tm.id"></el-option>
      </el-select>
    </el-form-item>
    <el-form-item label="SPU描述">
      <el-input type="textarea" v-model="spuForm.description" rows="4" placeholder="SPU描述"></el-input>
    </el-form-item>
    <el-form-item label="SPU图片">
      <!-- 
        file-list 指定要展示的是哪个图片数组,收集也是收集在这个数组当中 
          {name: 'food.jpg', url: 'https://xxx.cdn.com/xxx.jpg'}
        图片对象中必须有 name 和 url 属性,否则不能正常展示
      -->
      <el-upload action="/dev-api/admin/product/fileUpload" :file-list="spuImageList" list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove" :on-success="handleSuccess">
        <i class="el-icon-plus"></i>
      </el-upload>
      <el-dialog :visible.sync="dialogVisible">
        <img width="100%" :src="dialogImageUrl" alt="">
      </el-dialog>
    </el-form-item>
    <el-form-item label="销售属性">
      <el-select v-model="spuSaleAttrIdName" :placeholder="unUsedSpuSaleAttrList.length > 0 ? `还有 ${unUsedSpuSaleAttrList.length}项未选择` : '没有了'">
        <el-option :label="unUsedSpuSaleAttr.name" :value="`${unUsedSpuSaleAttr.id}:${unUsedSpuSaleAttr.name}`" v-for="unUsedSpuSaleAttr in unUsedSpuSaleAttrList" :key="unUsedSpuSaleAttr.id"></el-option>
      </el-select>
      <el-button type="primary" icon="el-icon-plus" @click="addSaleAttr" :disabled="!spuSaleAttrIdName">添加销售属性</el-button>
      <el-table :data="spuForm.spuSaleAttrList" border style="width: 100%; margin: 20px 0">
        <el-table-column type="index" label="序号" width="80px" align="center">
        </el-table-column>
        <el-table-column prop="saleAttrName" label="属性名" width="150px" align="center">
        </el-table-column>
        <el-table-column prop="prop" label="属性值名称列表" width="width">
          <template slot-scope="{row,$index}">
            <el-tag closable :disable-transitions="false" v-for="(spuSaleAttrValue,index) in row.spuSaleAttrValueList" :key="spuSaleAttrValue.id" @close="row.spuSaleAttrValueList.splice(index,1)">
              {{ spuSaleAttrValue.saleAttrValueName }}
            </el-tag>
            <!-- row.inputVisible 代表是否是编辑模式,由于一行只会有一个 input 框,所以挂在 row 身上 -->
            <el-input class="input-new-tag" v-if="row.inputVisible" v-model="row.inputValue" ref="saveTagInput" size="small" placeholder="名称" @keyup.enter.native="handleInputConfirm(row)" @blur="handleInputConfirm(row)">
            </el-input>
            <el-button v-else class="button-new-tag" size="small" @click="showInput(row)">+ 添加</el-button>
          </template>
        </el-table-column>
        <el-table-column prop="prop" label="操作" width="150px" align="center">
          <template slot-scope="{row,$index}">
            <HintButton type="danger" icon="el-icon-delete" size="mini" title="删除" @click="spuForm.spuSaleAttrList.splice($index,1)"></HintButton>
          </template>
        </el-table-column>
      </el-table>
      <el-button type="primary" @click="save">保存</el-button>
      <el-button @click="cancel">取消</el-button>
    </el-form-item>
  </el-form>
</template>

<script>
export default {
  name: 'SpuForm',
  data () {
    return {
      spuForm: {
        category3Id: 0,
        spuName: '',
        tmId: '',
        description: '',
        spuImageList: [],
        spuSaleAttrList: []
      },

      category3Id: '',

      // 控制图片预览的数据
      dialogImageUrl: '',
      dialogVisible: false,

      spuSaleAttrIdName: undefined,
      spuImageList: [],
      trademarkList: [],
      baseSaleAttrList: []
    }
  },
  methods: {
    // 删除图片成功后的回调
    handleRemove (file, fileList) {
      // file 是删除成功的那张图片, fileList 是删除成功后剩下的图片,所以 fileList 就是要收集的数据
      this.spuImageList = fileList
    },
    // 上传图片成功后的回调
    handleSuccess (response, file, fileList) {
      // response 是调用接口后的响应结果, file 是上传的图片对象, fileList 是上传成功后总的图片列表,就是要收集的数据
      this.spuImageList = fileList
    },
    // 预览大图, file 代表点击的图片文件
    handlePictureCardPreview (file) {
      this.dialogImageUrl = file.url;
      this.dialogVisible = true;
    },
    // 请求获取编辑初始化数据
    async initUpdateSpuFormData (spu) {
      this.category3Id = spu.category3Id
      // 获取 SPU 详情
      const result = await this.$API.spu.get(spu.id)
      if (result.code === 200) {
        this.spuForm = result.data
      }
      // 获取 SPU 图片列表数据
      const imgResult = await this.$API.sku.getSpuImageList(spu.id)
      if (imgResult.code === 200) {
        const spuImageList = imgResult.data
        /*
          给每个图片对象中添加 name 和 url 属性,否则照片墙不能正常展示
          在获取到数据,赋值给响应式数据 spuImageList 之前,将所有的数据处理好,最后一次性赋值给响应式数据
          那么数据对象中所有的属性都是响应式的
        */
        spuImageList.forEach(item => {
          item.name = item.imgName
          item.url = item.imgUrl
        })
        this.spuImageList = spuImageList
      }
      // 获取所有品牌列表数据
      const trademarkResult = await this.$API.trademark.getList()
      if (trademarkResult.code === 200) {
        this.trademarkList = trademarkResult.data
      }
      // 获取所有的销售属性数据
      const baseSaleAttrResult = await this.$API.spu.getSaleAttrList()
      if (baseSaleAttrResult.code === 200) {
        this.baseSaleAttrList = baseSaleAttrResult.data
      }
    },
    // 请求获取添加初始化数据
    async initAddSpuFormData (category3Id) {
      this.category3Id = category3Id
      // 获取所有品牌列表数据
      const trademarkResult = await this.$API.trademark.getList()
      if (trademarkResult.code === 200) {
        this.trademarkList = trademarkResult.data
      }
      // 获取所有的销售属性数据
      const baseSaleAttrResult = await this.$API.spu.getSaleAttrList()
      if (baseSaleAttrResult.code === 200) {
        this.baseSaleAttrList = baseSaleAttrResult.data
      }
    },
    // 点击添加销售属性
    addSaleAttr () {
      const [baseSaleAttrId, saleAttrName] = this.spuSaleAttrIdName.split(':')
      // 拼接对象
      const obj = {
        baseSaleAttrId,
        saleAttrName,
        spuSaleAttrValueList: []
      }
      this.spuForm.spuSaleAttrList.push(obj)
      // 将原来收集到的数据清空
      this.spuSaleAttrIdName = ''
    },
    // 点击添加按钮,切换为 input
    showInput (row) {
      // 显示当前行的输入框
      this.$set(row, 'inputVisible', true)
      // 自动获取焦点
      this.$nextTick(() => {
        this.$refs.saveTagInput.focus()
      })
    },
    // input 失去焦点或者回车之后的回调
    handleInputConfirm (row) {
      // 获取 input 输入的值
      const saleAttrValueName = row.inputValue
      const { baseSaleAttrId } = row

      // 判定
      if (saleAttrValueName.trim() === '') {
        row.inputValue = ''
        return
      }
      let isRepeat = row.spuSaleAttrValueList.some(item => item.saleAttrValueName === saleAttrValueName)
      if (isRepeat) {
        this.$message.info('输入的属性值名称不能重复')
        row.inputValue = ''
        return
      }

      // 构建为对象
      let obj = {
        saleAttrValueName,
        baseSaleAttrId
      }
      // 将对象添加到对应的属性值列表当中
      row.spuSaleAttrValueList.push(obj)
      // 将 input 输入的内容清空
      row.inputValue = ''
      // input 切换为按钮
      row.inputVisible = false
    },
    // 保存
    async save () {
      // 获取收集的参数数据
      const { spuForm, spuImageList, category3Id } = this
      // 整理图片列表(收集到的图片列表与需要的图片列表不符)
      spuForm.spuImageList = spuImageList.map(item => {
        // spuImageList 中包含原有图片和新上传的图片,两种图片返回的数据格式不同,需要进行处理
        return {
          imgName: item.name,
          imgUrl: item.imgUrl || item.response.data
        }
      })
      // 整理 category3Id
      spuForm.category3Id = category3Id
      // 删除属性当中的 inputVisible 和 inputValue
      spuForm.spuSaleAttrList.forEach(item => {
        delete item.inputVisible
        delete item.inputValue
      })
      // 发送请求
      try {
        await this.$API.spu.addUpdate(spuForm)
        this.$message.success('保存成功')
        // 返回列表页
        this.$emit('update:visible', false)
        // 通知父组件成功返回,重新请求获取数据
        this.$emit('successBack')
        // 清空当前组件 data 中所有数据
        this.resetData()
      } catch (error) {
        this.$message.error('保存失败')
      }
    },
    // 清空 data 中的数据
    resetData () {
      this.spuForm = {
        category3Id: 0,
        spuName: '',
        tmId: '',
        description: '',
        spuImageList: [],
        spuSaleAttrList: [
          {
            baseSaleAttrId: 0,
            saleAttrName: '',
            spuSaleAttrValueList: [],
          },
        ]
      }
      this.category3Id = ''

      this.dialogImageUrl = ''
      this.dialogVisible = false

      this.spuSaleAttrIdName = undefined
      this.spuImageList = []
      this.trademarkList = []
      this.baseSaleAttrList = []
    },
    // 取消操作
    cancel () {
      // 返回列表页
      this.$emit('update:visible', false)
      // 通知父组件,清空标识数据
      this.$emit('cancelBack')
      // 清空当前组件 data 中所有数据
      this.resetData()
    }
  },
  computed: {
    // 所有的销售属性除去自身后的剩余部分
    unUsedSpuSaleAttrList () {
      // 从所有的销售属性列表当中过滤出销售属性名称和自己的销售属性列表当中每个销售属性名称都不相同的
      return this.baseSaleAttrList.filter(baseSaleAttr => {
        return this.spuForm.spuSaleAttrList.every(spuSaleAttr => {
          return baseSaleAttr.name !== spuSaleAttr.saleAttrName
        })
      })
    }
  }
}
</script>

<style scoped>
.el-tag + .el-tag {
  margin-left: 10px;
}
.button-new-tag {
  margin-left: 10px;
  height: 32px;
  line-height: 30px;
  padding-top: 0;
  padding-bottom: 0;
}
.input-new-tag {
  width: 90px;
  margin-left: 10px;
  vertical-align: bottom;
}
</style>
